package com.google.appengine.a4ieve.entities;

import com.google.appengine.a4ieve.Helper;
import com.google.appengine.api.datastore.*;
import org.json.JSONObject;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class AchievementWrapper extends EntityWrapper{

    public static final String KIND_KEY = "Achievements";
    public static final String USER_ID_PROPERTY = "nickname";
    public static final String STATUS_PROPERTY = "status";
    public static final String ACHIEVEMENT_NAME = "achievement";
    public static final String ACHIEVEMENT_IMAGE = "blobdata";
    public static final String PROPOSED_BY = "proposedBy";
    public static final String APPROVED_BY = "approvedBy";
    public static final String IS_POSITIVE = "isPositive";
    public static final String ORIGINAL_PICTURE = "originalPicture";
    public static final String GROUP_PROPERTY = "group";
//    public static final PropertyProjection ID_PROJECTION = new PropertyProjection(USER_ID_PROPERTY, String.class);
    public static final PropertyProjection STATUS_PROJECTION = new PropertyProjection(STATUS_PROPERTY, String.class);
    public static final PropertyProjection POSITIVE_PROJECTION = new PropertyProjection(IS_POSITIVE, String.class);
    public static final PropertyProjection GROUP_PROJECTION = new PropertyProjection(GROUP_PROPERTY, String.class);

//    private Entity entity;
    private static final Map<String, ConversionMethod> JSON_PROPERTIES;
    static {
        Map<String, ConversionMethod> temp = new HashMap<String, ConversionMethod>();
        temp.put(USER_ID_PROPERTY, null);
        temp.put(STATUS_PROPERTY, null);
        temp.put(ACHIEVEMENT_NAME, null);
        temp.put(ACHIEVEMENT_IMAGE, new ConversionMethod() {
            @Override
            public Object convert(Object input) {
                return Helper.getImgEncoded(input);
            }
        });
        temp.put(PROPOSED_BY, null);
        temp.put(APPROVED_BY, null);
        temp.put(IS_POSITIVE, null);
        temp.put(ORIGINAL_PICTURE, null);
        JSON_PROPERTIES = Collections.unmodifiableMap(temp);
    }

    public AchievementWrapper(Entity entity) {
        super(entity);
    }

    @Override
    public JSONObject toJson() {
        return toJson(JSON_PROPERTIES);
    }

    @Override
    public Map<String, ConversionMethod> getProperties() {
        return JSON_PROPERTIES;
    }

    public static class AchievementBuilder {
        private String googleId;
        private String status;
        private String name;
        private Blob blobData;
        private String proposedBy;
        private String approvedBy;
        private Integer isPositive;
        private String originalPictureUrl;
        private String groupId;
        private Entity entity;

        public AchievementBuilder() {}

        public AchievementBuilder googleId(String id) {
            this.googleId = id;
            Key googleKey = KeyFactory.createKey(KIND_KEY, id);
            entity = new Entity(KIND_KEY, googleKey);
            entity.setProperty(USER_ID_PROPERTY, id);
            return this;
        }

        public AchievementBuilder status(String status) {
            if (this.googleId == null) {
                throw new IllegalStateException("Set google id prior to group id");
            }
            this.status = status;
            entity.setUnindexedProperty(STATUS_PROPERTY, this.status);
            return this;
        }

        public AchievementBuilder name(String name) {
            if (this.googleId == null) {
                throw new IllegalStateException("Set google id prior to group id");
            }
            this.name = name;
            entity.setProperty(ACHIEVEMENT_NAME, this.name);
            return this;
        }

        public AchievementBuilder blob(byte[] blobData) {
            if (this.googleId == null) {
                throw new IllegalStateException("Set google id prior to group id");
            }
            this.blobData = new Blob(blobData);
            entity.setUnindexedProperty(ACHIEVEMENT_IMAGE, this.blobData);
            return this;
        }

        public AchievementBuilder proposedBy(String proposer) {
            if (this.googleId == null) {
                throw new IllegalStateException("Set google id prior to group id");
            }
            this.proposedBy = proposer;
            entity.setProperty(PROPOSED_BY, this.proposedBy);
            return this;
        }

        public AchievementBuilder approveBy(String approver) {
            if (this.googleId == null) {
                throw new IllegalStateException("Set google id prior to group id");
            }
            this.approvedBy = approver;
            entity.setProperty(APPROVED_BY, this.approvedBy);
            return this;
        }

        public AchievementBuilder isPositive(int positive) {
            if (this.googleId == null) {
                throw new IllegalStateException("Set google id prior to group id");
            }
            this.isPositive = positive;
            entity.setUnindexedProperty(IS_POSITIVE, this.isPositive);
            return this;
        }

        public AchievementBuilder pictureUrl(String pictureUrl) {
            if (this.googleId == null) {
                throw new IllegalStateException("Set google id prior to group id");
            }
            this.originalPictureUrl = pictureUrl;
            entity.setProperty(ORIGINAL_PICTURE, this.originalPictureUrl);
            return this;
        }

        public AchievementBuilder groupId(String group) {
            if (this.googleId == null) {
                throw new IllegalStateException("Set google id prior to group id");
            }
            this.groupId = group;
            entity.setProperty(GROUP_PROPERTY, this.groupId);
            return this;
        }

        public AchievementWrapper build() {
            return new AchievementWrapper(this);
        }
    }

    private AchievementWrapper(AchievementBuilder builder) {
        this.entity = builder.entity;
    }

    public Entity getEntity(){
        return this.entity;
    }
}
